package starComponent.elements;

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Polygon;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import starComponent.Listeners.ListenerPopupCreateBranch;
import starComponent.utils.StringAndPolygon;
import tuio.components.LabelTouch;


/**
 * @author Charles Perin
 * 21 avr. 2011
 * LIMSI - INRIA Rennes
 * charles.perin@free.fr
 */
public class PopupCreateBranch extends LabelTouch{

	/**
	 * 
	 */
	private static final long serialVersionUID = -484875448287552517L;

	private StarComponent star;

	public static final int INSIDE_MARGIN = 20;

	private HashMap<Integer, StringAndPolygon> buttonMap = new HashMap<Integer, StringAndPolygon>();

	public PopupCreateBranch(StarComponent star, int x, int y){
		this.setStar(star);
		star.add(this);
		ListenerPopupCreateBranch listener = new ListenerPopupCreateBranch(this);
		addMouseListener(listener);
		addMouseMotionListener(listener);
		init(x,y);
	}

	public PopupCreateBranch(StarComponent star) {
		this.setStar(star);
	}

	protected void init(int x, int y){

		ArrayList<A_StarBranch> possibleBranches = new ArrayList<A_StarBranch>();
		ArrayList<A_StarBranch> allBranches = star.getControler().getAllPossibleBranchList();
		ArrayList<A_StarBranch> displayedBranches = star.getControler().getDisplayedBranchlist();

		for(A_StarBranch b:allBranches){
			if(!displayedBranches.contains(b)){
				possibleBranches.add(b);
			}
		}

		int i=0;
		for(i=0;i<possibleBranches.size();i++){
			buttonMap.put(i, new StringAndPolygon(possibleBranches.get(i).getName(), new Polygon()));
		}

		buttonMap.put(i, new StringAndPolygon("Cancel", new Polygon()));
		int starWidth = (int) star.getSize().getWidth();
		int starHeight = (int) star.getSize().getHeight();

		FontMetrics fm = star.getGraphics().getFontMetrics();
		int maxLength = 0;

		Iterator<Integer> iter = buttonMap.keySet().iterator();
		while(iter.hasNext()){
			int index = iter.next();
			int length = fm.stringWidth(buttonMap.get(index).getName());
			if(length>maxLength)maxLength=length;
		}

		int width = buttonMap.size()*2*fm.getHeight()+2*fm.getHeight();

		if(x<0)x=0;
		if(y<0)y=0;
		if(x+width>starWidth) x = starWidth-width;
		if(y+width>starHeight) y = starHeight-width;

		this.setBounds(x, y, width, width);

	}





	public void createPolygons() {
		Iterator<Integer> iter = buttonMap.keySet().iterator();
		while(iter.hasNext()){
			int index = iter.next();
			Point p1 = new Point(0, INSIDE_MARGIN+(getHeight()-2*INSIDE_MARGIN)*index/buttonMap.size());
			Point p2 = new Point(getWidth(), INSIDE_MARGIN+(getHeight()-2*INSIDE_MARGIN)*index/buttonMap.size());
			Point p3 = new Point(getWidth(), INSIDE_MARGIN+(getHeight()-2*INSIDE_MARGIN)*(index+1)/buttonMap.size());
			Point p4 = new Point(0, INSIDE_MARGIN+(getHeight()-2*INSIDE_MARGIN)*(index+1)/buttonMap.size());

			int[] xValues = new int[4];
			int[] yValues = new int[4];

			AffineTransform at = new AffineTransform();
			//si orientation du popup selon utilisateur
			if(star.getControler().isCollaborative()){
				double angle = -(Math.atan2(star.getNewBranchPoint().x-star.getCenter().x, star.getNewBranchPoint().y-star.getCenter().y));
				at.rotate(angle, getWidth()/2, getHeight()/2);
				at.transform(p1, p1);
				at.transform(p2, p2);
				at.transform(p3, p3);
				at.transform(p4, p4);
			}

			xValues[0] = p1.x;
			xValues[1] = p2.x;
			xValues[2] = p3.x;
			xValues[3] = p4.x;
			yValues[0] = p1.y;
			yValues[1] = p2.y;
			yValues[2] = p3.y;
			yValues[3] = p4.y;
			Polygon pTransform = new Polygon(xValues, yValues, 4);
			buttonMap.get(index).setPolygon(pTransform);

		}
	}

	@Override
	public void paintComponent(Graphics g){
		Graphics2D g2d = (Graphics2D)g;

		g2d.setFont(new Font("test", Font.BOLD, g2d.getFont().getSize()+5));

		FontMetrics metrics = g2d.getFontMetrics();

		//si orientation du popup selon utilisateur
		if(star.getControler().isCollaborative()){
			double angle = -(Math.atan2(star.getNewBranchPoint().x-star.getCenter().x, star.getNewBranchPoint().y-star.getCenter().y));
			g2d.rotate(angle, this.getWidth()/2, this.getHeight()/2);
		}

		Iterator<Integer> iter = buttonMap.keySet().iterator();
		while(iter.hasNext()){
			int index = iter.next();
			g2d.setColor(Color.BLACK);
			g2d.drawString(buttonMap.get(index).getName(),
					(getWidth()-metrics.stringWidth(buttonMap.get(index).getName()))/2,
					INSIDE_MARGIN+(getHeight()-2*INSIDE_MARGIN)*index/buttonMap.size()+metrics.getHeight());
		}


	}

	public void clickOn(int x, int y) {
		Iterator<Integer> iter = buttonMap.keySet().iterator();
		while(iter.hasNext()){
			int index = iter.next();
			StringAndPolygon sas = buttonMap.get(index);
			if(sas.getPolygon().contains(x, y)){
				if(sas.getName().equals("Cancel")){
					closePopup();
				}
				//si ajout de branche
				else{
					A_StarBranch branch = null;
					for(A_StarBranch b:star.getControler().getAllPossibleBranchList()){
						if(b.getName().equals(sas.getName())){
							branch = b;
						}
					}
					if(branch!=null){
						branch.setDisplayed(true);
						double newAngle = -Math.atan2(star.getNewBranchPoint().y-star.getCenter().y,star.getNewBranchPoint().x-star.getCenter().x);
						if(newAngle<0)newAngle = newAngle+2*Math.PI;
						branch.setAngle(newAngle);
						branch.updateBranch();
						star.getControler().getDisplayedBranchlist().add(branch);
						star.getControler().orderBranchesByAngle();
						star.getControler().createAllBranches();
						closePopup();
					}
				}
				break;
			}
		}
	}



	private void closePopup() {
		star.getControler().setCreateBranchPopupOpen(false);
		star.getControler().cancelCreateNewBranch();
		star.remove(this);
	}


	public void setStar(StarComponent star) {
		this.star = star;
	}

	public StarComponent getStar() {
		return star;
	}




}
